#include<iostream>
#include<vector>
#include<semaphore.h>
#include<pthread.h>
using namespace std;

const int default_cap = 10;
template<class T>
class RingQueue
{
public:
  RingQueue(int cap = default_cap ) :_cap(cap),c_step(0),p_step(0)
  {
    sem_init(&blank_sem,0,cap);//最初全是空间资源
    sem_init(&data_sem,0,0);
    ringQueue.resize(_cap,0);
  }
  ~RingQueue()
  {
    sem_destroy(&blank_sem);
    sem_destroy(&data_sem);
  }
  //生产者:1.P操作申请空间资源 2.放数据 3.++,通过取模保证环形 4.V操作发布数据资源
  void push(const T& val)
  {
    sem_wait(&blank_sem);
    ringQueue[p_step] = val;
    sem_post(&data_sem);
    //由于是单生产单消费,所以对p_step的操作可以放在临界区的后面
    p_step ++;
    p_step %= _cap;
  }
  //消费者:1.P操作申请数据资源 2.弹出数据 3.++,勇敢取模保证环形 4.V操作发布空间资源
  void pop(T* data) 
  {
    sem_wait(&data_sem);
    *data = ringQueue[c_step];
    sem_post(&blank_sem);
    c_step++;
    c_step %= _cap;
  }

private:
  vector<T> ringQueue;
  int _cap;
  sem_t blank_sem;//描述空间资源的个数
  sem_t data_sem;//描述数据资源的个数
  int c_step;
  int p_step;
};

